/**
 *                            License
 * THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS  
 * CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). 
 * THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW.  
 * ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR  
 * COPYRIGHT LAW IS PROHIBITED.
 * 
 * BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND  
 * AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE  
 * MAY BE CONSIDERED TO BE A CONTRACT,
 * THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED 
 * HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
 * 
 */
package com.lineage.server.packetclient;

import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.lineage.server.ClientThread;
import com.lineage.server.datatables.CharacterTable;
import com.lineage.server.datatables.MailTable;
import com.lineage.server.model.L1Clan;
import com.lineage.server.model.L1World;
import com.lineage.server.model.Instance.L1PcInstance;
import com.lineage.server.model.identity.L1ItemId;
import com.lineage.server.packetserver.S_Mail;
import com.lineage.server.packetserver.S_ServerMessage;
import com.lineage.server.templates.L1Mail;
import com.lineage.server.utils.collections.Lists;

/**
 * Class <code>C_Mail</code> 处理收到由客户端传来信件的封包.
 * 
 * @author jrwz
 * @version 2012-5-16下午02:59:52
 * @see com.lineage.server.packetclient
 * @since JDK1.7
 */
public class C_Mail extends ClientBasePacket {

    /** 返回一个字符串，表示客户端的数据包类型. */
    private static final String C_MAIL = "[C] C_Mail";
    /** 提示信息. */
    private static final Logger LOG = Logger.getLogger(C_Mail.class.getName());
    /** 一般. */
    private static final int TYPE_NORMAL_MAIL = 0;
    /** 血盟. */
    private static final int TYPE_CLAN_MAIL = 1;
    /** 保管箱. */
    private static final int TYPE_MAIL_BOX = 2;
    /** 类型:开启. */
    private static final int OPEN_0 = 0x00;
    /** 类型:开启. */
    private static final int OPEN_1 = 0x01;
    /** 类型:开启. */
    private static final int OPEN_2 = 0x02;
    /** 类型:读取. */
    private static final int READ_16 = 0x10;
    /** 类型:读取. */
    private static final int READ_17 = 0x11;
    /** 类型:读取. */
    private static final int READ_18 = 0x12;
    /** 类型:一般信纸. */
    private static final int STATIONERY_GENERAL_32 = 0x20;
    /** 类型:血盟信纸. */
    private static final int STATIONERY_CLAN_33 = 0x21;
    /** 类型:删除. */
    private static final int DELETE_48 = 0x30;
    /** 类型:删除. */
    private static final int DELETE_49 = 0x31;
    /** 类型:删除. */
    private static final int DELETE_50 = 0x32;
    /** 类型:保管箱储存. */
    private static final int BOX_SAVE_64 = 0x40;

    /**
     * 请求使用邮件.
     * 
     * @param abyte0
     *            资料
     * @param client
     *            客户端对象
     */
    public C_Mail(final byte[] abyte0, final ClientThread client) {
        super(abyte0);
        final int type = this.readC();
        final L1PcInstance pc = client.getActiveChar();

        switch (type) {
            // 开启
            case OPEN_0:
            case OPEN_1:
            case OPEN_2:
                if (pc != null) {
                    this.typeOpen(pc, type);
                }
                break;

            // 读取
            case READ_16:
            case READ_17:
            case READ_18:
                if (pc != null) {
                    final int mailId = this.readD();
                    this.typeRead(pc, type, mailId);
                }
                break;

            // 一般信纸
            case STATIONERY_GENERAL_32:
                if (pc != null) {
                    this.readH();
                    final String receiverName = this.readS();
                    final byte[] text = this.readByte();
                    this.typeStationeryGeneral(pc, type, receiverName, text);
                }
                break;

            // 血盟信纸
            case STATIONERY_CLAN_33:
                if (pc != null) {
                    this.readH();
                    final String clanName = this.readS();
                    final byte[] text = this.readByte();
                    this.typeStationeryClan(pc, type, clanName, text);
                }
                break;

            // 删除
            case DELETE_48:
            case DELETE_49:
            case DELETE_50:
                if (pc != null) {
                    final int mailId = this.readD();
                    this.typeDelete(pc, type, mailId);
                }
                break;

            // 保管箱储存
            case BOX_SAVE_64:
                if (pc != null) {
                    final int mailId = this.readD();
                    this.typeBoxSave(pc, type, mailId);
                }
                break;
            default:
                LOG.info("未处理的C_Mail类型: " + type);
                break;
        }
    }

    /**
     * 取得收信者的邮件数量.
     * 
     * @param receiverName
     *            收信者名称
     * @param type
     *            邮件类型
     * @return 邮件数量
     */
    private int getMailSizeByReceiver(final String receiverName, final int type) {
        final List<L1Mail> mails = Lists.newList();
        MailTable.getInstance();
        for (final L1Mail mail : MailTable.getAllMail()) {
            if (mail.getReceiverName().equalsIgnoreCase(receiverName)) {
                if (mail.getType() == type) {
                    mails.add(mail);
                }
            }
        }
        return mails.size();
    }

    @Override
    public final String getType() {
        return C_MAIL;
    }

    /**
     * 保管箱储存.
     * 
     * @param pc
     *            对象
     * @param type
     *            类型
     * @param mailId
     *            邮件编号
     */
    private void typeBoxSave(final L1PcInstance pc, final int type,
            final int mailId) {
        MailTable.getInstance().setMailType(mailId, TYPE_MAIL_BOX);
        final S_Mail msg = new S_Mail(mailId, type);
        pc.sendPackets(msg);
    }

    /**
     * 删除邮件.
     * 
     * @param pc
     *            对象
     * @param type
     *            类型
     * @param mailId
     *            邮件编号
     */
    private void typeDelete(final L1PcInstance pc, final int type,
            final int mailId) {
        MailTable.getInstance().deleteMail(mailId);
        final S_Mail msg = new S_Mail(mailId, type);
        pc.sendPackets(msg);
    }

    /**
     * 开启邮件.
     * 
     * @param pc
     *            对象
     * @param type
     *            类型
     */
    private void typeOpen(final L1PcInstance pc, final int type) {
        final S_Mail msg = new S_Mail(pc.getName(), type);
        pc.sendPackets(msg);
    }

    /**
     * 读取邮件.
     * 
     * @param pc
     *            对象
     * @param type
     *            类型
     * @param mailId
     *            邮件编号
     */
    private void typeRead(final L1PcInstance pc, final int type,
            final int mailId) {
        MailTable.getInstance();
        final L1Mail mail = MailTable.getMail(mailId);
        if (mail.getReadStatus() == 0) {
            MailTable.getInstance().setReadStatus(mailId);
        }
        pc.sendPackets(new S_Mail(mailId, type));
    }

    /**
     * 血盟邮件.
     * 
     * @param pc
     *            对象
     * @param type
     *            类型
     * @param clanName
     *            血盟名称
     * @param text
     *            内容
     */
    private void typeStationeryClan(final L1PcInstance pc, final int type,
            final String clanName, final byte[] text) {
        if (pc.getInventory().consumeItem(L1ItemId.ADENA, 1000)) {
            final L1Clan clan = L1World.getInstance().getClan(clanName);
            if (clan != null) {
                for (final String name : clan.getAllMembers()) {
                    final int size = this.getMailSizeByReceiver(name,
                            TYPE_CLAN_MAIL);
                    if (size >= 50) {
                        continue;
                    }
                    MailTable.getInstance().writeMail(TYPE_CLAN_MAIL, name, pc,
                            text);
                    final L1PcInstance clanPc = L1World.getInstance()
                            .getPlayer(name);
                    if (clanPc != null) { // 在线上
                        clanPc.sendPackets(new S_Mail(name, TYPE_CLAN_MAIL));
                    }
                }
            }
        } else {
            final S_ServerMessage msg = new S_ServerMessage(189);
            pc.sendPackets(msg); // \f1金币不足。
        }
    }

    /**
     * 一般邮件.
     * 
     * @param pc
     *            对象
     * @param type
     *            类型
     * @param receiverName
     *            收信者名称
     * @param text
     *            内容
     */
    private void typeStationeryGeneral(final L1PcInstance pc, final int type,
            final String receiverName, final byte[] text) {
        if (pc.getInventory().consumeItem(L1ItemId.ADENA, 50)) {
            final L1PcInstance receiver = L1World.getInstance().getPlayer(
                    receiverName);
            if (receiver != null) { // 对方在线上
                if (this.getMailSizeByReceiver(receiverName, TYPE_NORMAL_MAIL) >= 20) {
                    pc.sendPackets(new S_Mail(type));
                    return;
                }
                MailTable.getInstance().writeMail(TYPE_NORMAL_MAIL,
                        receiverName, pc, text);
                if (receiver.getOnlineStatus() == 1) {
                    receiver.sendPackets(new S_Mail(receiverName,
                            TYPE_NORMAL_MAIL));
                }
            } else { // 对方离线中
                try {
                    final L1PcInstance restorePc = CharacterTable.getInstance()
                            .restoreCharacter(receiverName);
                    if (restorePc != null) {
                        if (this.getMailSizeByReceiver(receiverName,
                                TYPE_NORMAL_MAIL) >= 20) {
                            pc.sendPackets(new S_Mail(type));
                            return;
                        }
                        MailTable.getInstance().writeMail(TYPE_NORMAL_MAIL,
                                receiverName, pc, text);
                    } else {
                        final S_ServerMessage msg = new S_ServerMessage(109,
                                receiverName);
                        pc.sendPackets(msg); // 没有叫%0的人。
                    }
                } catch (final Exception e) {
                    LOG.log(Level.SEVERE, e.getLocalizedMessage(), e);
                }
            }
        } else {
            final S_ServerMessage msg = new S_ServerMessage(189);
            pc.sendPackets(msg); // \f1金币不足。
        }
    }
}
